
package org.slusk.thynwor.corestructures;

import java.awt.Component;
import java.util.ArrayList;
import java.util.Properties;

import org.slusk.thynwor.corestructures.Drone.SignalType;
import org.slusk.thynwor.util.Coordinates;
import org.slusk.thynwor.util.Direction;

/**
 * Base class for all entities.
 * 
 * @author Shaun Lusk
 *
 */
public abstract class Entity implements Cloneable {
		
	public static enum EntityType {
		BOT
		, RESOURCE
		, THREAT
		, OBSTACLE
	}

	private final long id;
	private static int entitiesCreated;
	
	protected Properties config;
	
	Coordinates coords;
	protected GridMap map;
	protected Environment environment;
	private SignalType signal;
	
	static {
		entitiesCreated = 0;
	}	
	
	public Entity(Environment environment, Coordinates coordinates) {
		this.environment = environment;
		config = environment.getConfig();
		this.map = environment.getMap();
		this.coords = coordinates;
		this.id = entitiesCreated++;
	}
	
	
	/**
	 * Perform this Entity's actions. 
	 */
	public abstract void doTurnActions();
	public abstract Entity clone();
	public abstract char getDisplayCharacter();
	public abstract EntityType getEntityType();
	public abstract void render(Component cell);
	
	public Coordinates getCoordinates() { return coords; }
	public long getId() { return id; }
	public String toString() {return getInfo();}
	
	public SignalType getSignal() { return signal; }
	public void setSignal(SignalType signal) {this.signal = signal;}
	
	public String getInfo() {
		StringBuilder s = new StringBuilder();
		s.append(this.getClass().getSimpleName() + "\n");
		s.append("ID: " + id + "\n");
		s.append("Coordinates: " + coords + "\n");
		s.append("Signal: " + (signal == null ? "" : signal) + "\n");
		return s.toString();
	}
	
	/**
	 * Causes the Movable to move in a direction and fashion of its choice.
	 * @param direction
	 */
	public abstract void move();
	
	/**
	 * Attempts to force the entity to move in a specific direction; will fail
	 * if the space in the specified direction is not free; useful for rearrangement
	 * from the UI.
	 * @param direction
	 */
	public abstract void move(Direction direction);
	
	protected Direction pickRandomFreeDirection() {
		ArrayList<Direction> directions = map.findAvailableDirectionsForCoordinates(coords);
		if (directions.size() == 0) return null;
		return directions.get((int)(Math.random() * directions.size())); 
	}
	

	public Direction tryMoveInRandomDirection() {
		Direction direction = pickRandomFreeDirection();
		if (null != direction) {
			move(direction);
		}
		return direction;
	}

}
